package ch.nostromo.tiffanys.game.chess.pieces;

import ch.nostromo.lib.util.NosTools;
import ch.nostromo.tiffanys.game.board.Board;
import ch.nostromo.tiffanys.game.board.BoardException;

public abstract class ChessPiece {

  public static int checkDirection(Board board, int myPosition, int owner, int direction) throws BoardException {
    int result = 0;
    boolean exit = false;
    while (!exit) {
      int toField = myPosition + ((result + 1) * direction);
      boolean isEnemyPiece = board.isOpponentField(toField, owner);
      if (!board.isVoidField(toField) && (board.isEmptyField(toField) || isEnemyPiece)) {
        result++;
        if (isEnemyPiece)
          exit = true;
      } else {
        exit = true;
      }
    }
    return result;
  }

  public static boolean isKingAttacked(Board board, int owner) throws BoardException {
    int kingPos = board.getKingField(owner);
    return isKingAttacked(board, kingPos, owner);
  }
  
  public static boolean isKingAttacked(Board board, int kingPos, int owner) throws BoardException {

    int enemyColor = Board.invertOwner(owner);

    // Check for Knight Attacks
    if (NosTools.checkMask(board.getBoardArray()[kingPos + 19], Board.PIECE_KNIGHT) && NosTools.checkMask(board.getBoardArray()[kingPos + 19], enemyColor))
      return true;
    if (NosTools.checkMask(board.getBoardArray()[kingPos + 21], Board.PIECE_KNIGHT) && NosTools.checkMask(board.getBoardArray()[kingPos + 21], enemyColor))
      return true;
    if (NosTools.checkMask(board.getBoardArray()[kingPos + 12], Board.PIECE_KNIGHT) && NosTools.checkMask(board.getBoardArray()[kingPos + 12], enemyColor))
      return true;
    if (NosTools.checkMask(board.getBoardArray()[kingPos - 8], Board.PIECE_KNIGHT) && NosTools.checkMask(board.getBoardArray()[kingPos - 8], enemyColor))
      return true;
    if (NosTools.checkMask(board.getBoardArray()[kingPos - 19], Board.PIECE_KNIGHT) && NosTools.checkMask(board.getBoardArray()[kingPos - 19], enemyColor))
      return true;
    if (NosTools.checkMask(board.getBoardArray()[kingPos - 21], Board.PIECE_KNIGHT) && NosTools.checkMask(board.getBoardArray()[kingPos - 21], enemyColor))
      return true;
    if (NosTools.checkMask(board.getBoardArray()[kingPos - 12], Board.PIECE_KNIGHT) && NosTools.checkMask(board.getBoardArray()[kingPos - 12], enemyColor))
      return true;
    if (NosTools.checkMask(board.getBoardArray()[kingPos + 8], Board.PIECE_KNIGHT) && NosTools.checkMask(board.getBoardArray()[kingPos + 8], enemyColor))
      return true;

    // Check for diagonal Attacks
    int dcount = 0;
    int direction = 11;
    dcount = checkDirection(board, kingPos, owner, direction);
    if (NosTools.checkMask(board.getBoardArray()[kingPos + (dcount * direction)], enemyColor)
        && ((NosTools.checkMask(board.getBoardArray()[kingPos + (dcount * direction)], Board.PIECE_BISHOP) || (NosTools.checkMask(board.getBoardArray()[kingPos + (dcount * direction)], Board.PIECE_QUEEN)))))
      return true;
    if (dcount == 1 && NosTools.checkMask(board.getBoardArray()[kingPos + (dcount * direction)], Board.PIECE_KING))
      return true;
    direction = -11;
    dcount = checkDirection(board, kingPos, owner, direction);
    if (NosTools.checkMask(board.getBoardArray()[kingPos + (dcount * direction)], enemyColor)
        && ((NosTools.checkMask(board.getBoardArray()[kingPos + (dcount * direction)], Board.PIECE_BISHOP) || (NosTools.checkMask(board.getBoardArray()[kingPos + (dcount * direction)], Board.PIECE_QUEEN)))))
      return true;
    if (dcount == 1 && NosTools.checkMask(board.getBoardArray()[kingPos + (dcount * direction)], Board.PIECE_KING))
      return true;
    direction = 9;
    dcount = checkDirection(board, kingPos, owner, direction);
    if (NosTools.checkMask(board.getBoardArray()[kingPos + (dcount * direction)], enemyColor)
        && ((NosTools.checkMask(board.getBoardArray()[kingPos + (dcount * direction)], Board.PIECE_BISHOP) || (NosTools.checkMask(board.getBoardArray()[kingPos + (dcount * direction)], Board.PIECE_QUEEN)))))
      return true;
    if (dcount == 1 && NosTools.checkMask(board.getBoardArray()[kingPos + (dcount * direction)], Board.PIECE_KING))
      return true;
    direction = -9;
    dcount = checkDirection(board, kingPos, owner, direction);
    if (NosTools.checkMask(board.getBoardArray()[kingPos + (dcount * direction)], enemyColor)
        && ((NosTools.checkMask(board.getBoardArray()[kingPos + (dcount * direction)], Board.PIECE_BISHOP) || (NosTools.checkMask(board.getBoardArray()[kingPos + (dcount * direction)], Board.PIECE_QUEEN)))))
      return true;
    if (dcount == 1 && NosTools.checkMask(board.getBoardArray()[kingPos + (dcount * direction)], Board.PIECE_KING))
      return true;

    direction = 1;
    dcount = checkDirection(board, kingPos, owner, direction);
    if (NosTools.checkMask(board.getBoardArray()[kingPos + (dcount * direction)], enemyColor)
        && ((NosTools.checkMask(board.getBoardArray()[kingPos + (dcount * direction)], Board.PIECE_ROOK) || (NosTools.checkMask(board.getBoardArray()[kingPos + (dcount * direction)], Board.PIECE_QUEEN)))))
      return true;
    if (dcount == 1 && NosTools.checkMask(board.getBoardArray()[kingPos + (dcount * direction)], Board.PIECE_KING))
      return true;
    direction = -1;
    dcount = checkDirection(board, kingPos, owner, direction);
    if (NosTools.checkMask(board.getBoardArray()[kingPos + (dcount * direction)], enemyColor)
        && ((NosTools.checkMask(board.getBoardArray()[kingPos + (dcount * direction)], Board.PIECE_ROOK) || (NosTools.checkMask(board.getBoardArray()[kingPos + (dcount * direction)], Board.PIECE_QUEEN)))))
      return true;
    if (dcount == 1 && NosTools.checkMask(board.getBoardArray()[kingPos + (dcount * direction)], Board.PIECE_KING))
      return true;
    direction = 10;
    dcount = checkDirection(board, kingPos, owner, direction);
    if (NosTools.checkMask(board.getBoardArray()[kingPos + (dcount * direction)], enemyColor)
        && ((NosTools.checkMask(board.getBoardArray()[kingPos + (dcount * direction)], Board.PIECE_ROOK) || (NosTools.checkMask(board.getBoardArray()[kingPos + (dcount * direction)], Board.PIECE_QUEEN)))))
      return true;
    if (dcount == 1 && NosTools.checkMask(board.getBoardArray()[kingPos + (dcount * direction)], Board.PIECE_KING))
      return true;
    direction = -10;
    dcount = checkDirection(board, kingPos, owner, direction);
    if (NosTools.checkMask(board.getBoardArray()[kingPos + (dcount * direction)], enemyColor)
        && ((NosTools.checkMask(board.getBoardArray()[kingPos + (dcount * direction)], Board.PIECE_ROOK) || (NosTools.checkMask(board.getBoardArray()[kingPos + (dcount * direction)], Board.PIECE_QUEEN)))))
      return true;
    if (dcount == 1 && NosTools.checkMask(board.getBoardArray()[kingPos + (dcount * direction)], Board.PIECE_KING))
      return true;

    // Check for pawn Attacks
    int pawnDirection = 1;
    if (owner == Board.OWNER_BLACK)
      pawnDirection = -1;

    if (NosTools.checkMask(board.getBoardArray()[kingPos + (11 * pawnDirection)], Board.PIECE_PAWN) && NosTools.checkMask(board.getBoardArray()[kingPos + (11 * pawnDirection)], enemyColor)) {
      return true;
    }
    if (NosTools.checkMask(board.getBoardArray()[kingPos + (9 * pawnDirection)], Board.PIECE_PAWN) && NosTools.checkMask(board.getBoardArray()[kingPos + (9 * pawnDirection)], enemyColor)) {
      return true;
    }

    return false;

  }

}